export function uniLen(str: string): number {
    return str.split('').reduce((sum: number, char: string) =>
        sum += (char.charCodeAt(0) >= 0
            && char.charCodeAt(0) <= 128) ? 1 : 2, 0);
}

export function clamp(str: string, maxChars: number = 5, suffix: string = '...'): string {
    if (str.length === 0) {
        return '';
    }
    const toCodePoint = (unicodeSurrogates) =>{
        const r = [];
        let c = 0;
        let p = 0;
        let i = 0;
        while (i < unicodeSurrogates.length) {
            const pos = i;
            c = unicodeSurrogates.charCodeAt(i++);// 返回位置的字符的 Unicode 编码
            if (c === 0xfe0f) {
                continue;
            }
            if (p!==0) {
                const value = (0x10000 + ((p - 0xD800) << 10) + (c - 0xDC00));
                r.push({
                    v: value,
                    pos: pos,
                }); // 计算4字节的unicode
                p = 0;
            }
            else if (0xD800 <= c && c <= 0xDBFF) {
                p = c; // 如果unicode编码在oxD800-0xDBff之间，则需要与后一个字符放在一起
            }
            else {
                r.push({
                    v: c,
                    pos: pos,
                }); // 如果是2字节，直接将码点转为对应的十六进制形式
            }
        }
        return r;
    };

    suffix = suffix == null ? '...' : suffix;
    maxChars *= 2;

    const codeArr = toCodePoint(str);
    let numChar = 0;
    let index = 0;
    for (let i = 0; i < codeArr.length; ++i) {
        const code = codeArr[i].v;
        let add = 1;
        if (code >= 128) {
            add = 2;
        }

        // 如果超过了限制，则按上一个为准
        if (numChar + add > maxChars) {
            break;
        }

        index = i;

        // 累加
        numChar += add;
    }

    if (codeArr.length - 1 === index) {
        return str;
    }

    const more = suffix == null ? 1 : 0;

    return str.substring(0, codeArr[index - more].pos + 1) + suffix;

};